package com.lwtek.demo;

import android.Manifest;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.journeyapps.barcodescanner.BarcodeEncoder;
import com.lwtek.demo.adapter.DevicesViewAdapter;
import com.lwtek.demo.databinding.ActivityMainBinding;
import com.lwtek.demo.databinding.DialogLayoutBinding;
import com.lwtek.scanner.auto.ScannerAutoService;
import com.lwtek.scanner.ble.ScannerBleDevice;
import com.lwtek.scanner.ble.ScannerBleService;
import com.lwtek.scanner.core.ScannerDevice;
import com.lwtek.scanner.core.ScannerService;
import com.lwtek.scanner.spp.ScannerSppDevice;
import com.lwtek.scanner.spp.ScannerSppService;
import com.permissionx.guolindev.PermissionX;

import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    private DevicesViewAdapter devicesViewAdapter;
    private Dialog dialog;
    private Dialog progressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        setSupportActionBar(binding.appbar);

        PermissionX.init(this).permissions(
                        Manifest.permission.BLUETOOTH,
                        Manifest.permission.BLUETOOTH_ADMIN,
                        Manifest.permission.BLUETOOTH_SCAN,
                        Manifest.permission.BLUETOOTH_CONNECT,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                .request((allGranted, grantedList, deniedList) -> {
                });

        devicesViewAdapter = new DevicesViewAdapter(this);
        binding.devicesView.setLayoutManager(new LinearLayoutManager(this));
        binding.devicesView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        binding.devicesView.setAdapter(devicesViewAdapter);

        binding.connectBtn.setOnClickListener(v -> connect());

        ScannerService.onBluetoothState(new ScannerService.BluetoothStateCallback() {

            @Override
            public void onOpened() {
                runOnUiThread(() -> {
                    Toast.makeText(MainActivity.this, "Bluetooth is enabled.", Toast.LENGTH_SHORT).show();
                });
            }

            @Override
            public void onClosed() {
                runOnUiThread(() -> {
                    Toast.makeText(MainActivity.this, "Bluetooth is off", Toast.LENGTH_SHORT).show();
                });
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        search();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == R.id.refresh) {
            search();
        } else if (item.getItemId() == R.id.bleConnect) {
            bleAutoConnect();
        } else if (item.getItemId() == R.id.sppConnect) {
            sppAutoConnect();
        } else if (item.getItemId() == R.id.hidConnect) {
            hidAutoConnect();
        } else if (item.getItemId() == R.id.hogConnect) {
            hogAutoConnect();
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Search device
     */
    public void search() {
        devicesViewAdapter.clear();
        // Start scanning device (BLE)
        ScannerBleService.getBondedDevices().forEach(scanner -> {
            devicesViewAdapter.addBonded(scanner);
        });
        ScannerBleService.search(scanner -> {
            // Add device to list
            devicesViewAdapter.add(scanner);
        });
        // Start scanning device (SPP)
        ScannerSppService.getBondedDevices().forEach(scanner -> {
            devicesViewAdapter.addBonded(scanner);
        });
        ScannerSppService.search(scanner -> {
            devicesViewAdapter.add(scanner);
        });
    }

    /**
     * BLE automatic connection
     */
    public void bleAutoConnect() {
        showQrcodeDialog("BLE", ScannerAutoService.ble((success, device) -> {
            if (success) {
                if (device != null) {
                    ScannerDevice scanner = ScannerBleDevice.from(device);
                    scanner.connect(((success1, message) -> {
                        // "success" indicates whether the connection was successful, and "message" is the message notification.
                        if (success1) {
                            MyApplication.setDevice(scanner);
                            Intent intent = new Intent(this, InfoActivity.class);
                            startActivity(intent);
                            progressDialog.dismiss();
                        }
                    }));
                }
            } else {
                progressDialog.dismiss();
            }
        }, step -> {
            if (step == 0) {
                dialog.dismiss();
                progressDialog = ProgressDialog.show(MainActivity.this, "", "Connecting", true);
            }
        }));
    }

    /**
     * SPP自动连接
     */
    public void sppAutoConnect() {
        showQrcodeDialog("SPP", ScannerAutoService.spp((success, device) -> {
            if (success) {
                if (device != null) {
                    ScannerDevice scanner = ScannerSppDevice.from(device);
                    scanner.connect(((success1, message) -> {
                        // "success" indicates whether the connection was successful, and "message" is the message notification.
                        if (success1) {
                            MyApplication.setDevice(scanner);
                            Intent intent = new Intent(this, InfoActivity.class);
                            startActivity(intent);
                            progressDialog.dismiss();
                        }
                    }));
                }
            } else {
                progressDialog.dismiss();
            }
        }, step -> {
            if (step == 0) {
                dialog.dismiss();
                progressDialog = ProgressDialog.show(MainActivity.this, "", "Connecting", true);
            }
        }));
    }

    /**
     * HID自动连接
     */
    public void hidAutoConnect() {
        showQrcodeDialog("HID", ScannerAutoService.hid((success, device) -> {
            progressDialog.dismiss();
        }, step -> {
            if (step == 0) {
                dialog.dismiss();
                progressDialog = ProgressDialog.show(MainActivity.this, "", "Connecting", true);
            }
        }));
    }

    /**
     * HOG自动连接
     */
    public void hogAutoConnect() {
        showQrcodeDialog("HOG", ScannerAutoService.hog((success, device) -> {
            progressDialog.dismiss();
        }, step -> {
            if (step == 0) {
                dialog.dismiss();
                progressDialog = ProgressDialog.show(MainActivity.this, "", "Connecting", true);
            }
        }));
    }

    public void connect() {
        // Stop scanning equipment
        ScannerBleService.stopSearch();
        ScannerSppService.stopSearch();
        ScannerDevice scanner = devicesViewAdapter.getCurrent();
        if (scanner == null) {
            return;
        }

        // Connecting devices
        scanner.connect((success, message) -> {
            // "success" indicates whether the connection was successful, and "message" is the message notification.
            if (success) {
                MyApplication.setDevice(scanner);
                Intent intent = new Intent(this, InfoActivity.class);
                startActivity(intent);
            }
        });
    }

    /**
     * Display QR code Dialog
     */
    public void showQrcodeDialog(String title, String code) {
        if (code == null) {
            runOnUiThread(() -> Toast.makeText(this, "Unauthorized permissions", Toast.LENGTH_SHORT).show());
            return;
        }
        Dialog dialog = new Dialog(this);
        DialogLayoutBinding dialogLayoutBinding = DialogLayoutBinding.inflate(getLayoutInflater());
        dialog.setContentView(dialogLayoutBinding.getRoot());
        dialogLayoutBinding.titleView.setText(title);
        dialogLayoutBinding.qrcodeView.setImageBitmap(createQrcode(code));
        dialog.setCanceledOnTouchOutside(true);
        dialog.setOnCancelListener(v -> {
            ScannerAutoService.stop();
        });
        dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
        dialog.show();
        this.dialog = dialog;
    }

    /**
     * Generate QR code
     */
    public Bitmap createQrcode(String content) {
        int width = 400;
        int height = 400;
        // Setting QR code parameters in HashMap
        Map map = new HashMap();
        // Set outer margin
        map.put(EncodeHintType.MARGIN, 0);
        try {
            // Use an encoder to generate a QR code
            return new BarcodeEncoder().encodeBitmap(content, BarcodeFormat.QR_CODE, width, height, map);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }

}